﻿#region Usings

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Linq;
using FeedReader.Data;
using FeedReader.Expections;
using FeedReader.Xml;
using Image = System.Drawing.Image;

#endregion

namespace FeedReader
{
    public class Feed
    {
        private static bool _useCache;
        private static List<FeedItemFilter> _feedItemFilters = new List<FeedItemFilter>();

        public Feed(string url_path, string cacheFolder, List<FeedItemFilter> itemFilters)
        {
            LogEvents.InvokeOnDebug(new FeedArgs("Add new feed " + url_path + " using cache folder " + cacheFolder));
            UrlPath = url_path;
            if (!string.IsNullOrEmpty(cacheFolder))
            {
                if (Utils.IsValidPath(cacheFolder))
                {
                    LogEvents.InvokeOnDebug(new FeedArgs(cacheFolder + " is a valid path. Now checking if the cache folder already exists"));
                    if (!Directory.Exists(cacheFolder))
                    {
                        LogEvents.InvokeOnDebug(new FeedArgs(cacheFolder + " doesn't exist. Now create a new folder."));
                        Directory.CreateDirectory(cacheFolder);
                    }
                    LogEvents.InvokeOnDebug(new FeedArgs(cacheFolder + " exist. Caching for feed is now enabled."));
                    if (!cacheFolder.EndsWith(@"\")) cacheFolder += @"\";
                    CacheFolder = cacheFolder;
                    _useCache = true;
                    _feedItemFilters = itemFilters;
                }
                else
                {
                    _useCache = false;
                    throw new FeedCacheFolderNotValid(cacheFolder + " is not a valid path. Caching disabled");
                }
            }
            else
            {
                _useCache = false;
                throw new FeedNoCacheFolderExpection("Cache folder path is empty. Caching disabled");
            }
            LastUpdateSuccessful = false;
            Items = new List<FeedItem>();
            //Update();
        }

        public Feed(string url_path)
        {
            LogEvents.InvokeOnDebug(new FeedArgs("Add new feed without using cache"));
            UrlPath = url_path;
            _useCache = false;
            LastUpdateSuccessful = false;
            Items = new List<FeedItem>();
            //Update();
        }

        public Feed()
        {
            Items = new List<FeedItem>();
        }

        public static bool DeleteCache()
        {
            LogEvents.InvokeOnDebug(new FeedArgs("Try to delete cache"));
            if (Directory.Exists(CacheFolder))
            {
                try
                {
                    Directory.Delete(CacheFolder, true);
                    LogEvents.InvokeOnInfo(new FeedArgs("Deleted cache successful"));
                    return true;
                }
                catch (Exception ex)
                {
                    LogEvents.InvokeOnError(new FeedArgs("Error deleting cache", ex.Message, ex.StackTrace));
                }

            }
            LogEvents.InvokeOnInfo(new FeedArgs("Error deleting cache. Directory " + CacheFolder + " doesn't exist"));
            return false;
        }

        public string Title { get; set; }
        public string Description { get; set; }
        public static string CacheFolder { get; protected set; }
        public List<FeedItem> Items { get; set; }
        public FeedType Type { get; set; }
        public Image Image { get; set; }
        public string ImagePath { get; set; }
        public string UrlPath { get; set; }
        public DateTime LastUpdate { get; set; }
        public bool LastUpdateSuccessful { get; set; }

        public virtual bool Update(bool downloadImages)
        {
            Feed nFeed = new Feed {UrlPath = this.UrlPath};
            LastUpdateSuccessful = false;

            LogEvents.InvokeOnDebug(new FeedArgs("Try downloading/loading feed from " + UrlPath));
            XDocument xmlFeed;
            try
            {
                xmlFeed = XDocument.Load(UrlPath);
                LogEvents.InvokeOnDebug(new FeedArgs("Download/Loading of feed " + UrlPath + " successful"));
            }
            catch (Exception ex)
            {
                LogEvents.InvokeOnError(new FeedArgs("Error downloading/loading feed from url/path " + UrlPath, ex.Message, ex.StackTrace));
                return false;
            }

            if (!_useCache)
            {

                LogEvents.InvokeOnInfo(new FeedArgs("Parsing feed from url/path " + UrlPath + " without using cache"));
                if (FeedRdfXmlParser.TryParse(xmlFeed, ref nFeed, downloadImages, _feedItemFilters))
                {
                    Type = FeedType.RDF;
                    LogEvents.InvokeOnInfo(new FeedArgs("Parsing RDF feed from url/path " + UrlPath + " successfull"));
                }
                else if (FeedRssXmlParser.TryParse(xmlFeed, ref nFeed, downloadImages, _feedItemFilters))
                {
                    LogEvents.InvokeOnInfo(new FeedArgs("Parsing RSS feed from url/path " + UrlPath + " successfull"));
                    Type = FeedType.RSS;
                }
                else if (FeedAtomXmlParser.TryParse(xmlFeed, ref nFeed, downloadImages, _feedItemFilters))
                {
                    LogEvents.InvokeOnInfo(new FeedArgs("Parsing ATOM feed from url/path " + UrlPath + " successfull"));
                    Type = FeedType.ATOM;
                }
                else
                {
                    LogEvents.InvokeOnInfo(new FeedArgs("Parsing feed from url/path " + UrlPath + " unsuccessful. See above for errors or warnings"));
                    return false;
                }
            }
            else
            {
                LogEvents.InvokeOnInfo(new FeedArgs("Parsing feed from url/path " + UrlPath + " into cache folder " + CacheFolder, ""));
                if (FeedRdfXmlParser.TryParse(xmlFeed, ref nFeed, CacheFolder, downloadImages, _feedItemFilters))
                {
                    LogEvents.InvokeOnInfo(new FeedArgs("Parsing RDF feed from url/path " + UrlPath + " successfull"));
                    Type = FeedType.RDF;
                }
                else if (FeedRssXmlParser.TryParse(xmlFeed, ref nFeed, CacheFolder, downloadImages, _feedItemFilters))
                {
                    LogEvents.InvokeOnInfo(new FeedArgs("Parsing RSS feed from url/path " + UrlPath + " successfull"));
                    Type = FeedType.RSS;
                }
                else if (FeedAtomXmlParser.TryParse(xmlFeed, ref nFeed, CacheFolder, downloadImages, _feedItemFilters))
                {
                    LogEvents.InvokeOnInfo(new FeedArgs("Parsing ATOM feed from url/path " + UrlPath + " successfull"));
                    Type = FeedType.ATOM;
                }
                else
                {
                    LogEvents.InvokeOnInfo(new FeedArgs("Parsing feed from url/path " + UrlPath + " unsuccessful. See above for errors or warnings"));
                    return false;
                }
            }
            Description = nFeed.Description;
            LastUpdate = DateTime.Now;
            LastUpdateSuccessful = true;
            Image = nFeed.Image;
            Items = nFeed.Items;
            Title = nFeed.Title;
            ImagePath = nFeed.ImagePath;
            return true;
        }
    }
}